﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;

using ECCIT;
using ECCIT.Data;
using ECCIT.Business.DAL;

using OgilvyOne.UKNow.Common;
using OgilvyOne.UKNow.Globalization;
using OgilvyOne.UKNow.Utility;
using OgilvyOne.UKNow.Model;
using OgilvyOne.UKNow.IDAL;

namespace OgilvyOne.UKNow.DAL
{
    public class WarmupDAL : UKNowBaseDAL, IDALWarmup
    {
        private const string TBL_NAME               = "UKNOW_WARMUP";

        private const string COL_LANG_ID            = "COL_LANG_ID";
        private const string COL_WARMUP_ID             = "COL_WARMUP_ID";
        private const string COL_WARMUP_IMG           = "COL_WARMUP_IMG";
        private const string COL_WARMUP_DESC           = "COL_WARMUP_DESC";
        private const string COL_MEMBER_ID         = "COL_MEMBER_ID";
        private const string COL_WARMUP_STATE          = "COL_WARMUP_STATE";
        private const string COL_WARMUP_VOTE          = "COL_WARMUP_VOTE";
        private const string COL_WARMUP_FWD          = "COL_WARMUP_FWD";
        private const string COL_WARMUP_CMT_COUNT = "COL_WARMUP_CMT_COUNT";
        private const string COL_WARMUP_INSERT_TIME    = "COL_WARMUP_INSERT_TIME";
        private const string COL_WARMUP_UPDATE_TIME    = "COL_WARMUP_UPDATE_TIME";

        public override string TableName { get { return TBL_NAME; } }

        public override Type ModelType { get { return typeof(WarmupModel); } }

        [PrimaryKey]
        public IField LanguageID { get { return FieldFactory.Create(ModelType, "LanguageID", ColumnFactory.CreateColumn(COL_LANG_ID, DataType.Int)); } }
        [PrimaryKey]
        public IField ID { get { return FieldFactory.Create(ModelType, "ID", ColumnFactory.CreateColumn(COL_WARMUP_ID, DataType.Int)); } }
        
        public IField ImagePath { get { return FieldFactory.Create(ModelType, "ImagePath", ColumnFactory.CreateColumn(COL_WARMUP_IMG, DataType.String, 200)); } }
        public IField Description { get { return FieldFactory.Create(ModelType, "Description", ColumnFactory.CreateColumn(COL_WARMUP_DESC, DataType.String, 200)); } }
        public IField AuthorID { get { return FieldFactory.Create(ModelType, "AuthorID", ColumnFactory.CreateColumn(COL_MEMBER_ID, DataType.Int)); } }
        public IField State { get { return FieldFactory.Create(ModelType, "State", ColumnFactory.CreateColumn(COL_WARMUP_STATE, DataType.Int)); } }
        public IField VoteCount { get { return FieldFactory.Create(ModelType, "VoteCount", ColumnFactory.CreateColumn(COL_WARMUP_VOTE, DataType.Int)); } }
        public IField ForwardCount { get { return FieldFactory.Create(ModelType, "ForwardCount", ColumnFactory.CreateColumn(COL_WARMUP_FWD, DataType.Int)); } }
        public IField CommentCount { get { return FieldFactory.Create(ModelType, "CommentCount", ColumnFactory.CreateColumn(COL_WARMUP_CMT_COUNT, DataType.Int)); } }
        public IField InsertedTime { get { return FieldFactory.Create(ModelType, "InsertedTime", ColumnFactory.CreateColumn(COL_WARMUP_INSERT_TIME, DataType.DateTime)); } }
        public IField UpdatedTime { get { return FieldFactory.Create(ModelType, "UpdatedTime", ColumnFactory.CreateColumn(COL_WARMUP_UPDATE_TIME, DataType.DateTime)); } }

        public override IField[] InsertFields { get { return new IField[] { LanguageID, ID, ImagePath, Description, AuthorID, State, VoteCount, ForwardCount, CommentCount, InsertedTime, UpdatedTime }; } }
        public override IField[] SelectFields { get { return InsertFields; } }
        public override IField[] UpdateFields { get { return new IField[] { LanguageID, ID, ImagePath, Description, AuthorID, State, VoteCount, ForwardCount, InsertedTime, UpdatedTime }; } }

        public WarmupDAL() { }

        public WarmupDAL(LanguageType languageType) { this.Language = LanguageFactory.Create(languageType); }

        private void SetForeignKeyModel(WarmupModel model)
        {
            if (model == null) return;
            if (model.AuthorID.HasValue)
            model.Author = new MemberDAL().GetMemberModelByID(model.AuthorID);
        }

        #region IDALWarmup Members

        public WarmupModel GetWarmupModelByID(int? id)
        {
            WarmupModel model = (WarmupModel)GetModelByPrimaryKey(this.GetType(), new KeyValuePair<IField, object>[] { new KeyValuePair<IField, object>(LanguageID, (int)this.Language.LanguageType), new KeyValuePair<IField, object>(this.ID, id) });
            SetForeignKeyModel(model);
            return model;
        }

        public IList<WarmupModel> GetAllWarmupModels()
        {
            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));
            IList<WarmupModel> models = GetModels(builder.ToSqlCommand(), PagingParameterFactory.CreateNonPagingParameter(SortingParameterFactory.CreateInstance(UpdatedTime.PropertyName, SortOrder.Desc))).List.Cast<WarmupModel>().ToList();
            foreach (WarmupModel model in models)
                SetForeignKeyModel(model);

            return models;
        }

        public PagingList GetPublishedWarmupModels(PagingParameter pagingParams)
        {
            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_WARMUP_STATE, 1, SearchConditionOperator.Equals));
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            if (pagingParams == null)
                pagingParams = PagingParameterFactory.CreateNonPagingParameter(null);

            if (pagingParams.SortingParameter == null)  //如果没有排序参数，默认按照最后更新时间倒排序
                pagingParams.SortingParameter = SortingParameterFactory.CreateInstance(UpdatedTime.PropertyName, SortOrder.Desc);

            PagingList list = GetModels(whereClause, pagingParams);
            foreach (WarmupModel model in list.List)
                SetForeignKeyModel(model);

            return list;
        }

        public PagingList GetAllPublishedWarmupModels(PagingParameter pagingParams)
        {
            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_WARMUP_STATE, 1, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            if (pagingParams == null)
                pagingParams = PagingParameterFactory.CreateNonPagingParameter(null);

            if (pagingParams.SortingParameter == null)  //如果没有排序参数，默认按照最后更新时间倒排序
                pagingParams.SortingParameter = SortingParameterFactory.CreateInstance(UpdatedTime.PropertyName, SortOrder.Desc);

            PagingList list = GetModels(whereClause, pagingParams);
            foreach (WarmupModel model in list.List)
                SetForeignKeyModel(model);

            return list;
        }

        public ResultInfo Save(WarmupModel modelInfo)
        {
            if (modelInfo == null) throw new ArgumentNullException("modelInfo");

            ResultInfo result = new ResultInfo(false);

            try
            {
                int rowsAffected = 0;
                if (modelInfo.ID == null)   // insert
                {
                    modelInfo.ID = SqlUtil.GetMaxRecordID(TableName, COL_WARMUP_ID, COL_LANG_ID, (int)this.Language.LanguageType);
                    modelInfo.State = 1;    // 强制将状态置为已发布
                    rowsAffected = Insert(modelInfo, null);
                }
                else // update
                {
                    rowsAffected = UpdateByPrimaryKey(modelInfo, null);
                }

                if (rowsAffected > 0)
                {
                    result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Success);
                    result.Result = true;
                    result.ReturnObject = modelInfo;
                }
            }
            catch (Exception ex)
            {
                result.Exception = ex;
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Exception, ex);
            }

            return result;
        }

        public ResultInfo Delete(IList<int?> idList)
        {
            ResultInfo result = new ResultInfo(false);
            using (IDbConnection conn = DBHelper.GetDbConnection())
            {
                conn.Open();
                IDbTransaction trans = conn.BeginTransaction();
                try
                {
                    foreach (int? id in idList)
                        DeleteModelByPrimaryKey(trans, this.GetType(), new KeyValuePair<IField, object>[] { new KeyValuePair<IField, object>(LanguageID, (int)this.Language.LanguageType), new KeyValuePair<IField, object>(this.ID, id) });

                    trans.Commit();
                    result.Result = true;
                    result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Delete, Enums.ActionResult.Success);
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Delete, Enums.ActionResult.Exception, ex);
                }
                finally
                {
                    trans.Dispose();
                }
            }

            return result;
        }

        public ResultInfo Publish(IList<int?> idList)
        {
            ResultInfo result = new ResultInfo(false);

            IField[] updatedFields = new IField[] { this.State };
            IDataParameter[] parms = DBHelper.GetDataParameters(updatedFields);
            parms[0].Value = 1;

            string ids = "";
            foreach (int? id in idList)
                ids += (ids == string.Empty) ? id.ToString() : "," + id.ToString();

            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(InSearchCondition.CreateInstance(COL_WARMUP_ID, DataType.Int, ids));
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            string cmdText = DBHelper.GetUpdateCommandText(this.TableName, updatedFields, whereClause);

            try
            {
                DBHelper.ExecuteNonQuery(cmdText, parms);
                result.Result = true;
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Publish, Enums.ActionResult.Success);
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Publish, Enums.ActionResult.Exception, ex);
            }

            return result;
        }

        public ResultInfo UnPublish(IList<int?> idList)
        {
            ResultInfo result = new ResultInfo(false);

            IField[] updatedFields = new IField[] { this.State };
            IDataParameter[] parms = DBHelper.GetDataParameters(updatedFields);
            parms[0].Value = 0;

            string ids = "";
            foreach (int? id in idList)
                ids += (ids == string.Empty) ? id.ToString() : "," + id.ToString();

            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(InSearchCondition.CreateInstance(COL_WARMUP_ID, DataType.Int, ids));
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            string cmdText = DBHelper.GetUpdateCommandText(this.TableName, updatedFields, whereClause);

            try
            {
                DBHelper.ExecuteNonQuery(cmdText, parms);
                result.Result = true;
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.UnPublish, Enums.ActionResult.Success);
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.UnPublish, Enums.ActionResult.Exception, ex);
            }

            return result;
        }

        public ResultInfo Vote(int? id)
        {
            ResultInfo result = new ResultInfo(false);

            if (id == null || !id.HasValue)
                return result;

            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(InSearchCondition.CreateInstance(COL_WARMUP_ID, DataType.Int, id));
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            string cmdText = string.Format("UPDATE {0} SET {1}={1}+1 {2}", TBL_NAME, COL_WARMUP_VOTE, whereClause);

            try
            {
                DBHelper.ExecuteNonQuery(cmdText);
                result.Result = true;
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Vote, Enums.ActionResult.Success);
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Vote, Enums.ActionResult.Exception, ex);
            }

            return result;
        }

        public ResultInfo Forward(int? id)
        {
            ResultInfo result = new ResultInfo(false);

            if (id == null || !id.HasValue)
                return result;

            WhereClauseBuilder builder = WhereClauseBuilder.CreateInstance(SearchConditionJoinOperator.AND);
            builder.Conditions.Add(InSearchCondition.CreateInstance(COL_WARMUP_ID, DataType.Int, id));
            builder.Conditions.Add(CommonSearchCondition.CreateInstance(COL_LANG_ID, (int)this.Language.LanguageType, SearchConditionOperator.Equals));

            string whereClause = builder.ToSqlCommand();
            string cmdText = string.Format("UPDATE {0} SET {1}={1}+1 {2}", TBL_NAME, COL_WARMUP_FWD, whereClause);

            try
            {
                DBHelper.ExecuteNonQuery(cmdText);
                result.Result = true;
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Forward, Enums.ActionResult.Success);
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Forward, Enums.ActionResult.Exception, ex);
            }

            return result;
        }

        public ResultInfo AddCommentCount(int? id)
        {
            ResultInfo result = new ResultInfo(false);
            string cmd = string.Format("UPDATE {0} SET {1}={1}+1 WHERE {2}={3} and {4}={5}", TBL_NAME, COL_WARMUP_CMT_COUNT, COL_LANG_ID, (int)this.Language.LanguageType, COL_WARMUP_ID, id);
            try
            {
                int rowsAffected = DBHelper.ExecuteNonQuery(cmd);
                if (rowsAffected > 0)
                {
                    result.Result = true;
                    result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Success);
                }
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Exception, ex);
                result.ReturnObject = cmd;
            }

            return result;
        }

        public ResultInfo SubtractCommentCount(int? id)
        {
            ResultInfo result = new ResultInfo(false);
            string cmd = string.Format("UPDATE {0} SET {1}={1}-1 WHERE {2}={3} and {4}={5}", TBL_NAME, COL_WARMUP_CMT_COUNT, COL_LANG_ID, (int)this.Language.LanguageType, COL_WARMUP_ID, id);
            try
            {
                int rowsAffected = DBHelper.ExecuteNonQuery(cmd);
                if (rowsAffected > 0)
                {
                    result.Result = true;
                    result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Success);
                }
            }
            catch (Exception ex)
            {
                result.Message = Language.GetAlertMessage(ModelType, Enums.Action.Save, Enums.ActionResult.Exception, ex);
                result.ReturnObject = cmd;
            }

            return result;
        }

        public SortingParameter SortedByVoteCount(SortOrderPair sortOrder)
        {
            return SortingParameterFactory.CreateInstance(VoteCount.PropertyName, sortOrder);
        }

        public SortingParameter SortedByForwardCount(SortOrderPair sortOrder)
        {
            return SortingParameterFactory.CreateInstance(ForwardCount.PropertyName, sortOrder);
        }

        public SortingParameter SortedByCommentCount(SortOrderPair sortOrder)
        {
            return SortingParameterFactory.CreateInstance(CommentCount.PropertyName, sortOrder);
        }
        #endregion
    }
}
